package com.dtflys.easyel.runtime.wrapper;

import com.dtflys.easyel.exception.EasyElAccessException;
import com.dtflys.easyel.exception.EasyElAmbiguousMethodsException;
import com.dtflys.easyel.runtime.EasyElObject;
import com.dtflys.easyel.runtime.MetaClass;
import com.dtflys.easyel.runtime.MetaClassFactory;

import java.lang.reflect.InvocationTargetException;

/**
 * @author gongjun[jun.gong@thebeastshop.com]
 * @since v1.0.0
 */
public abstract class Wrapper implements EasyElObject {

    private final Object originalObject;

    private final Class originalClass;

    private final MetaClass metaClass;


    public Wrapper(Object originalObject, Class originalClass) {
        this(originalObject, originalClass, MetaClassFactory.getMetaClass(originalClass));
    }

    public Wrapper(Object originalObject, Class originalClass, MetaClass metaClass) {
        this.originalObject = originalObject;
        this.originalClass = originalClass;
        this.metaClass = metaClass;
    }

    public Object getOriginalObject() {
        return originalObject;
    }

    public Class getOriginalClass() {
        return originalClass;
    }

    @Override
    public Object access(String name) throws IllegalAccessException, EasyElAccessException, InvocationTargetException {
        return metaClass.access(originalObject, name);
    }

    @Override
    public void inject(String name, Object value) throws IllegalAccessException, EasyElAccessException, InvocationTargetException {
        metaClass.inject(originalObject, name, value);
    }

    @Override
    public Object invokeMethod(String methodName, Object[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, EasyElAmbiguousMethodsException {
        return metaClass.invokeMethod(originalObject, methodName, args);
    }

    @Override
    public MetaClass getMetaClass() {
        return metaClass;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Wrapper) {
            return getOriginalObject().equals(((Wrapper) obj).getOriginalObject());
        }
        return false;
    }

    @Override
    public String toString() {
        return originalObject.toString();
    }
}
